<?php
/**
 * Project:     drylamp - rapid application development framework for php
 * File:        DBAdapter.php
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *
 * @copyright 2009-2010 Ilya St.
 * @author Ilya St. <provided at gmail dot com>
 * @version 1.0
 */

class DBAdapterException extends Exception {}
class DBAdapterConnectFail extends DBAdapterException {}
class DBAdapterQueryFail extends DBAdapterException {}

class DBAdapter {
  
  public static $link;
  protected $mLoginInfo = NULL;
  
  const ASSOC          = 1;
  const AFFECTED_ROWS  = 2;
  const LAST_INSERT_ID = 3;
  const NONE           = 4;
  
  protected static $queriesCount;
  
  /**
   *  Meant to be initialized by autoloader
   */ 
  public static function init() {
    self::ConnectToDB();
  }

  
  public static function ConnectToDB(Array $pConnectionConf = NULL)
  {
    if ( !is_null($pConnectionConf) ) {
      $host    = $pConnectionConf['host'];
      $db_name = $pConnectionConf['db_name'];
      $user    = $pConnectionConf['user'];
      $pass    = $pConnectionConf['pass'];
      self::$mLoginInfo = $pConnectionConf;
    }
     else {
       $host    = Conf::get('DB_HOST');
       $db_name = Conf::get('DB_NAME');
       $user    = Conf::get('DB_USER');
       $pass    = Conf::get('DB_PASS');
     }
    self::$link = @ new mysqli( $host, $user, $pass, $db_name );
    
    
    if ( mysqli_connect_errno() ) {
      $errNo  = mysqli_connect_error();
      $errMsg = mysqli_connect_error();
      throw new DBAdapterConnectFail( "Failed to connect to the database: " . $errMsg . "(".$errNo.")" , 0 );
    }
    return TRUE;    
  }
  
  /**
   * Executes a query and returns an associative array, representing the resulting projection.
   * If results is empty - null is returned.
   * @param string $sql
   */
  public static function queryAssoc($sql) {
    return self::query($sql, self::ASSOC);
  }
  
  /**
   * Executes a query and returns number of affected rows.
   * @param string $sql
   */
  public static function queryAffectedRows($sql) {
    return self::query($sql, self::AFFECTED_ROWS);
  }
  
  /**
   * Executes a query and returns last insert ID, or 0 if not applicable.
   * @param string $sql
   */
  public static function queryLastInsertId($sql) {
     return self::query($sql, self::LAST_INSERT_ID);
  }
  
  /**
   * Executes a query and doesn't return any result
   * @param string $sql
   */
  public static function queryVoid($sql) {
  	 self::query($sql, self::NONE);
  }
  
  public static function query( $pSQL, $pPostPrParam = NULL ) {
    $result = self::getQueryResult($pSQL);
    
    switch( $pPostPrParam )
    {
      case self::AFFECTED_ROWS :
                    return  self::$link->affected_rows;
           break;
           
      case self::LAST_INSERT_ID:
                    return self::$link->insert_id;
          break;     
      
          
      case self::NONE:  break;
          
      case self::ASSOC :      
      default:
                while ( $row = $result->fetch_assoc() ) {
                      $rows[] = $row;
                    }
                    return $rows;
           break;  
    } 
  }
  
  
  public static function getQueryResult( $pSQL ) {
    $link = self::getLink();

    self::$queriesCount++;
    $result = $link->query( $pSQL );
    if ( !$result ) {
    	$errMsg   = "N/A";
    	$errCode  = "N/A";
    	@$errMsg  = self::$link->error;
    	@$errCode = self::$link->errno;
    	
      throw new DBAdapterQueryFail(  $pSQL . ' : '.$errMsg . '('.$errCode.')' , 1 );
    }
    return $result;
  }
  
  
  public static function getLink() {
    if ( !( self::$link instanceof mysqli ) || @self::$link->ping() == false ) {
      //attempt to reconnect if disconected (latest login info array is used):
      self::ConnectToDB(); 
    }
    return self::$link;
  }
  
  public static function escapeString($pStr) {
  	if (get_magic_quotes_runtime() == 1) $pStr = stripslashes($pStr);
  	return self::getLink()->real_escape_string($pStr);
  }
  
  public static function getQueriesCount() {
  	return self::$queriesCount;
  }
  
  public static function startTransaction() {
  	self::query("START TRANSACTION" , self::NONE);
  }
  
  public static function rollback() {
  	self::query("ROLLBACK" , self::NONE);
  }

  public static function commit() {
  	self::query("COMMIT" , self::NONE);
  }
  
}

